package top.z.orm.core.osql;

/**
 * 为面向对象方式操作数据库提供封装的条件
 * <br>用户需要保证SQL的书写顺序,如order by应在group by的后面
 * <br>setMultiply,setAdd,set等方法仅用于SQL Update语句的set部分
 */
public interface Condition extends ConditionAssistant {

    /**
     * 添加用于分页时设置开始的页数(仅用于SQL的select),无书写顺序限制
     *
     * @param start 开始下标(从0或1开始,eg:MySQL是0,Oracle是1)
     * @return Condition
     */
    Condition start(Integer start);

    /**
     * 添加用于分页时设置每页返回的记录数量(仅用于SQL的select),无书写顺序限制
     *
     * @param size 结果集大小 大于等于1
     * @return Condition
     */
    Condition size(Integer size);

    /**
     * 设置IncludeType过滤参数.op,between,notBetween方法设置的字段,不受includeType的值影响
     * <br>如果Condition没有使用该方法设置,则按默认过滤方式处理.
     * <br>无书写顺序限制
     *
     * @param includeType IncludeType
     * @return Condition
     */
    Condition setIncludeType(IncludeType includeType);

    /**
     * 添加一个表达式条件,此方法不能用于SQL的update set
     *
     * @param field 字段名
     * @param Op    操作符.
     * @param value 字段对应的值
     * @return Condition
     */
    Condition op(String field, Op Op, Object value);

    /**
     * 添加一个表达式条件
     * <br>此方法不能用于SQL的update set
     *
     * @param field1 first field
     * @param Op     操作符
     * @param field2 second field
     * @return Condition
     */
    Condition opWithField(String field1, Op Op, String field2);

    /**
     * 默认自动加 'and'
     *
     * @return Condition
     */
    Condition and();

    /**
     * 添加 'or'.Add 'or'.
     *
     * @return Condition
     */
    Condition or();

    /**
     * 添加左括号
     *
     * @return Condition
     */
    Condition lParentheses();

    /**
     * 添加右括号
     *
     * @return Condition
     */
    Condition rParentheses();

    /**
     * @param field field
     * @param low   low
     * @param high  high
     * @return Condition
     */
    Condition between(String field, Number low, Number high);

    /**
     * @param field field
     * @param low   low
     * @param high  high
     * @return Condition
     */
    Condition notBetween(String field, Number low, Number high);

    /**
     * @param field field
     * @param low   low
     * @param high  high
     * @return Condition
     */
    Condition between(String field, String low, String high);

    /**
     * @param field field
     * @param low   low
     * @param high  high
     * @return Condition
     */
    Condition notBetween(String field, String low, String high);

    /**
     * @param field field
     * @return Condition
     */
    Condition groupBy(String field);

    /**
     * eg:having("count(*)>5")  --> having count(*)>5
     *
     * @param expressionStr 表达式字符串,field不会被转化.
     * @return Condition
     */
    Condition having(String expressionStr);

    /**
     * eg: having(FunctionType.MIN, "field", Op.ge, 60)-->having min(field)>=60
     *
     * @param functionType SQL函数类型
     * @param field        实体字段,会被命名转换(如果需要)
     * @param Op           操作类型
     * @param value        值
     * @return Condition
     */
    Condition having(FunctionType functionType, String field, Op Op, Number value);

    /**
     * eg: orderBy("price")-->order by price
     *
     * @param field 用于排序的字段名
     * @return Condition
     */
    Condition orderBy(String field);

    /**
     * eg: orderBy("price", OrderType.DESC)-->order by price desc
     *
     * @param field     用于排序的字段名
     * @param orderType 排序类型(asc或desc)
     * @return Condition
     */
    Condition orderBy(String field, OrderType orderType);

    /**
     * eg: orderBy(FunctionType.MAX, "total", OrderType.DESC)-->order by max(total) desc
     *
     * @param functionType SQL函数类型
     * @param field        用于排序的字段名
     * @param orderType    排序类型(asc或desc)
     * @return Condition
     */
    Condition orderBy(FunctionType functionType, String field, OrderType orderType);

    /**
     * 设置需要更新的字段(仅用于SQL的update set),字段在自身基础上变化
     * <br>eg: setAdd("price",2.0)--> price=price+2.0
     *
     * @param field field
     * @param num   num
     * @return Condition
     */
    Condition setAdd(String field, Number num);

    /**
     * 设置需要更新的字段(仅用于SQL的update set),字段在自身基础上变化
     * <br>eg: setMultiply("price",1.05)--> price=price*1.05
     *
     * @param field field
     * @param num   num
     * @return Condition
     */
    Condition setMultiply(String field, Number num);

    /**
     * 设置需要更新的字段(仅用于SQL的update set),字段在自身基础上变化
     * <br>eg:setAdd("price","delta")--> price=price+delta
     *
     * @param field          field
     * @param otherFieldName other field name
     * @return Condition
     */
    Condition setAdd(String field, String otherFieldName);

    /**
     * 设置需要更新的字段(仅用于SQL的update set),字段在自身基础上变化
     * <br>eg: setMultiply("price","delta")--> price=price*delta
     *
     * @param field          field
     * @param otherFieldName other field name
     * @return Condition
     */
    Condition setMultiply(String field, String otherFieldName);

    /**
     * 设置需要更新的字段(仅用于SQL的update set);当要更新的字段也需要用于where条件时,可用该方法
     * <br>eg: set("maxId", 1000) --> maxId=1000
     *
     * @param fieldName field name
     * @param num       num
     * @return Condition
     */
    Condition set(String fieldName, Number num);

    /**
     * 设置需要更新的字段(仅用于SQL的update set);当要更新的字段也需要用于where条件时,可用该方法
     * <br>eg: set("name", 'bee') --> name='bee'
     *
     * @param fieldName field name
     * @param value     value
     * @return Condition
     */
    Condition set(String fieldName, String value);

    /**
     * set one field with other field value
     * eg: setWithField(field1,field2)--> set field1=field2
     *
     * @param field1 first field
     * @param field2 second field
     * @return Condition
     */
    Condition setWithField(String field1, String field2);

    /**
     * 指定需要查询的部分字段(仅用于SQL的select)
     *
     * @param fieldList 需要查询的字段,多个用逗号隔开
     * @return Condition
     */
    Condition selectField(String fieldList);

    /**
     * 设置使用函数查询结果
     * <br>eg: condition.selectFun(FunctionType.COUNT, "*");-->count(*)
     *
     * @param functionType SQL函数类型
     * @param fieldForFun  用于函数统计的字段名
     * @return Condition
     */
    Condition selectFun(FunctionType functionType, String fieldForFun);

    /**
     * 设置使用函数查询结果
     * <br>eg:selectFun(FunctionType.MAX, "score","maxScore") --> max(score) as maxScore
     *
     * @param functionType SQL函数类型.Function type of SQL.
     * @param fieldForFun  用于函数统计的字段名.field name for function.
     * @param alias        统计结果的别名.alias name for the function result.
     * @return Condition
     */
    Condition selectFun(FunctionType functionType, String fieldForFun, String alias);

    /**
     * 锁定查询的部分记录(仅用于SQL的单个表select),无书写顺序限制
     *
     * @return Condition
     */
    Condition forUpdate();
}